package point

import (
	"fmt"
	"os/exec"

	"github.com/go-viper/mapstructure/v2"
	"github.com/spf13/viper"
)

type NetworkConfig struct {
	Ethernets map[string]EthernetConfig `mapstructure:"ethernets"`
	Renderer  string                    `mapstructure:"renderer"`
	Version   int                       `mapstructure:"version"`
}

type EthernetConfig struct {
	Addresses   []string         `mapstructure:"addresses"`
	Dhcp4       bool             `mapstructure:"dhcp4"`
	Routes      []RouteConfig    `mapstructure:"routes"`
	Nameservers NameserverConfig `mapstructure:"nameservers"`
}

type RouteConfig struct {
	To  string `mapstructure:"to"`
	Via string `mapstructure:"via"`
}

type NameserverConfig struct {
	Addresses []string `mapstructure:"addresses"`
}

func NewNameServerConfig(dns string) NameserverConfig {
	return NameserverConfig{
		Addresses: []string{dns},
	}
}

func NewRouteConfig(gateway string) RouteConfig {
	return RouteConfig{
		To:  "default",
		Via: gateway,
	}
}

func NewNetworkConfig(ethernetConfig map[string]EthernetConfig) *NetworkConfig {
	return &NetworkConfig{
		Ethernets: ethernetConfig,
		Renderer:  "networkd",
		Version:   2,
	}
}

func NewStaticEthernetConfig(ip, dns, gateway, netMask string) EthernetConfig {
	ethConfig := EthernetConfig{
		Dhcp4:       false,
		Routes:      []RouteConfig{NewRouteConfig(gateway)},
		Nameservers: NewNameServerConfig(dns),
	}

	if netMask == "255.0.0.0" {
		ethConfig.Addresses = []string{ip + "/8"}
	} else if netMask == "255.255.0.0" {
		ethConfig.Addresses = []string{ip + "/16"}
	} else if netMask == "255.255.255.0" {
		ethConfig.Addresses = []string{ip + "/24"}
	} else if netMask == "255.255.255.255" {
		ethConfig.Addresses = []string{ip + "/32"}
	} else {
		ethConfig.Addresses = []string{ip + "/24"}
	}

	return ethConfig
}

func NewDhcpEthernetConfig() EthernetConfig {
	return EthernetConfig{
		Dhcp4: true,
	}
}

type WanXConnectPoint struct {
	index int
}

func NewWanXConnectPoint() *WanXConnectPoint {
	return &WanXConnectPoint{}
}

func (s *WanXConnectPoint) Get() any {
	return ""
}

func (s *WanXConnectPoint) Set(val ...any) bool {
	fmt.Println("ip -->", wanxIp)
	fmt.Println("dns -->", wanxDns)
	fmt.Println("gateway -->", wanxGateway)
	fmt.Println("subNetMask -->", wanxSubNetMask)
	fmt.Println("mode -->", wanxMode)

	v := viper.New()
	v.SetConfigName("config")
	v.SetConfigType("yaml")
	v.AddConfigPath("/etc/netplan")

	err := v.ReadInConfig()
	if err != nil {
		fmt.Println("read config file failed, err -->", err)
		return false
	}

	var config *NetworkConfig

	if wanxMode == "static" || wanxMode == "manual" {
		config = NewNetworkConfig(map[string]EthernetConfig{"eth1": NewStaticEthernetConfig(wanxIp, wanxDns, wanxGateway, wanxSubNetMask)})
	} else if wanxMode == "DHCP" || wanxMode == "auto" || wanxMode == "dhcp" {
		// config = NewNetworkConfig(map[string]EthernetConfig{"eth1": NewDhcpEthernetConfig()})
		// if wanxMode == "dhcp" || wanxMode == "auto" {
		exec.Command("netplan", "set", "network.ethernets.eth1.dhcp4=true").Run()
		return exec.Command("netplan", "apply").Run() != nil
		// }
	}
	var cfgMap map[string]interface{}
	if err := mapstructure.Decode(config, &cfgMap); err != nil {
		fmt.Printf("结构体转map失败: %v\n", err)
		return false
	}

	// cfgMap = map[string]interface{}{
	// 	"network": cfgMap,
	// }

	// if err := v.MergeConfigMap(cfgMap); err != nil {
	// 	fmt.Printf("配置合并失败: %v\n", err)
	// 	return false
	// }

	v.Set("network", cfgMap)

	if err := v.WriteConfig(); err != nil {
		fmt.Printf("写入文件失败: %v\n", err)
		return false
	}

	if err := exec.Command("netplan", "apply").Run(); err != nil {
		fmt.Println("netplan apply failed, err -->", err)
		return false
	}

	return true
}

func (s *WanXConnectPoint) SetRoute(str string) PointInterface {
	s.index = int(str[len("wan")]) - '0'
	return s
}
